{{>licenseInfo}}
package {{package}};

import {{invokerPackage}}.ApiClient;
import {{invokerPackage}}.ApiException;
import {{invokerPackage}}.ApiResponse;
import {{invokerPackage}}.Pair;

{{#imports}}
import {{import}};
{{/imports}}

import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;

{{#useBeanValidation}}
import jakarta.validation.constraints.*;
import jakarta.validation.Valid;

{{/useBeanValidation}}
{{#hasFormParamsInSpec}}
import org.apache.http.HttpEntity;
import org.apache.http.NameValuePair;
import org.apache.http.entity.mime.MultipartEntityBuilder;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.client.entity.UrlEncodedFormEntity;

{{/hasFormParamsInSpec}}
import java.io.InputStream;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.OutputStream;
import java.net.http.HttpRequest;
import java.nio.channels.Channels;
import java.nio.channels.Pipe;
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.time.Duration;

import java.util.ArrayList;
import java.util.StringJoiner;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.function.Consumer;
{{#asyncNative}}

import java.util.concurrent.CompletableFuture;
{{/asyncNative}}

{{>generatedAnnotation}}
{{#operations}}
public class {{classname}} {
  private final HttpClient memberVarHttpClient;
  private final ObjectMapper memberVarObjectMapper;
  private final String memberVarBaseUri;
  private final Consumer<HttpRequest.Builder> memberVarInterceptor;
  private final Duration memberVarReadTimeout;
  private final Consumer<HttpResponse<InputStream>> memberVarResponseInterceptor;
  private final Consumer<HttpResponse<String>> memberVarAsyncResponseInterceptor;

  public {{classname}}() {
    this(new ApiClient());
  }

  public {{classname}}(ApiClient apiClient) {
    memberVarHttpClient = apiClient.getHttpClient();
    memberVarObjectMapper = apiClient.getObjectMapper();
    memberVarBaseUri = apiClient.getBaseUri();
    memberVarInterceptor = apiClient.getRequestInterceptor();
    memberVarReadTimeout = apiClient.getReadTimeout();
    memberVarResponseInterceptor = apiClient.getResponseInterceptor();
    memberVarAsyncResponseInterceptor = apiClient.getAsyncResponseInterceptor();
  }
  {{#asyncNative}}

  private ApiException getApiException(String operationId, HttpResponse<String> response) {
    String message = formatExceptionMessage(operationId, response.statusCode(), response.body());
    return new ApiException(response.statusCode(), message, response.headers(), response.body());
  }
  {{/asyncNative}}
  {{^asyncNative}}

  protected ApiException getApiException(String operationId, HttpResponse<InputStream> response) throws IOException {
    String body = response.body() == null ? null : new String(response.body().readAllBytes());
    String message = formatExceptionMessage(operationId, response.statusCode(), body);
    return new ApiException(response.statusCode(), message, response.headers(), body);
  }
  {{/asyncNative}}

  private String formatExceptionMessage(String operationId, int statusCode, String body) {
    if (body == null || body.isEmpty()) {
      body = "[no body]";
    }
    return operationId + " call failed with: " + statusCode + " - " + body;
  }

  {{#operation}}
  {{#vendorExtensions.x-group-parameters}}
  {{#hasParams}}
  /**
   * {{summary}}
   * {{notes}}
   * @param apiRequest {@link API{{operationId}}Request}
   {{#returnType}}
   * @return {{#asyncNative}}CompletableFuture&lt;{{/asyncNative}}{{returnType}}{{#asyncNative}}&gt;{{/asyncNative}}
   {{/returnType}}
   {{^returnType}}
   {{#asyncNative}}
   * @return CompletableFuture&lt;Void&gt;
   {{/asyncNative}}
   {{/returnType}}
   * @throws ApiException if fails to make API call
   {{#isDeprecated}}
   * @deprecated
   {{/isDeprecated}}
   {{#externalDocs}}
   * {{description}}
   * @see <a href="{{url}}">{{summary}} Documentation</a>
   {{/externalDocs}}
   */
  {{#isDeprecated}}
  @Deprecated
  {{/isDeprecated}}
  public {{#returnType}}{{#asyncNative}}CompletableFuture<{{{returnType}}}>{{/asyncNative}}{{^asyncNative}}{{{returnType}}}{{/asyncNative}}{{/returnType}}{{^returnType}}{{#asyncNative}}CompletableFuture<Void>{{/asyncNative}}{{^asyncNative}}void{{/asyncNative}}{{/returnType}} {{operationId}}(API{{operationId}}Request apiRequest) throws ApiException {
    {{#allParams}}
    {{{dataType}}} {{paramName}} = apiRequest.{{paramName}}();
    {{/allParams}}
    {{#returnType}}return {{/returnType}}{{^returnType}}{{#asyncNative}}return {{/asyncNative}}{{/returnType}}{{operationId}}({{#allParams}}{{paramName}}{{^-last}}, {{/-last}}{{/allParams}});
  }

  /**
   * {{summary}}
   * {{notes}}
   * @param apiRequest {@link API{{operationId}}Request}
   * @return {{#asyncNative}}CompletableFuture&lt;{{/asyncNative}}ApiResponse&lt;{{returnType}}{{^returnType}}Void{{/returnType}}&gt;{{#asyncNative}}&gt;{{/asyncNative}}
   * @throws ApiException if fails to make API call
   {{#isDeprecated}}
   * @deprecated
   {{/isDeprecated}}
   {{#externalDocs}}
   * {{description}}
   * @see <a href="{{url}}">{{summary}} Documentation</a>
   {{/externalDocs}}
   */
  {{#isDeprecated}}
  @Deprecated
  {{/isDeprecated}}
  public {{#asyncNative}}CompletableFuture<{{/asyncNative}}ApiResponse<{{{returnType}}}{{^returnType}}Void{{/returnType}}>{{#asyncNative}}>{{/asyncNative}} {{operationId}}WithHttpInfo(API{{operationId}}Request apiRequest) throws ApiException {
    {{#allParams}}
    {{{dataType}}} {{paramName}} = apiRequest.{{paramName}}();
    {{/allParams}}
    return {{operationId}}WithHttpInfo({{#allParams}}{{paramName}}{{^-last}}, {{/-last}}{{/allParams}});
  }

  {{/hasParams}}
  {{/vendorExtensions.x-group-parameters}}
  /**
   * {{summary}}
   * {{notes}}
   {{#allParams}}
   * @param {{paramName}} {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{^isContainer}}{{#defaultValue}}, default to {{.}}{{/defaultValue}}{{/isContainer}}){{/required}}
   {{/allParams}}
   {{#returnType}}
   * @return {{#asyncNative}}CompletableFuture&lt;{{/asyncNative}}{{returnType}}{{#asyncNative}}&gt;{{/asyncNative}}
   {{/returnType}}
   {{^returnType}}
   {{#asyncNative}}
   * @return CompletableFuture&lt;Void&gt;
   {{/asyncNative}}
   {{/returnType}}
   * @throws ApiException if fails to make API call
   {{#isDeprecated}}
   * @deprecated
   {{/isDeprecated}}
   {{#externalDocs}}
   * {{description}}
   * @see <a href="{{url}}">{{summary}} Documentation</a>
   {{/externalDocs}}
   */
  {{#isDeprecated}}
  @Deprecated
  {{/isDeprecated}}
  public {{#returnType}}{{#asyncNative}}CompletableFuture<{{{returnType}}}>{{/asyncNative}}{{^asyncNative}}{{{returnType}}}{{/asyncNative}}{{/returnType}}{{^returnType}}{{#asyncNative}}CompletableFuture<Void>{{/asyncNative}}{{^asyncNative}}void{{/asyncNative}}{{/returnType}} {{operationId}}({{#allParams}}{{{dataType}}} {{paramName}}{{^-last}}, {{/-last}}{{/allParams}}) throws ApiException {
    {{^asyncNative}}
    {{#returnType}}ApiResponse<{{{.}}}> localVarResponse = {{/returnType}}{{operationId}}WithHttpInfo({{#allParams}}{{paramName}}{{^-last}}, {{/-last}}{{/allParams}});
    {{#returnType}}
    return localVarResponse.getData();
    {{/returnType}}
    {{/asyncNative}}
    {{#asyncNative}}
    try {
      HttpRequest.Builder localVarRequestBuilder = {{operationId}}RequestBuilder({{#allParams}}{{paramName}}{{^-last}}, {{/-last}}{{/allParams}});
      return memberVarHttpClient.sendAsync(
          localVarRequestBuilder.build(),
          HttpResponse.BodyHandlers.ofString()).thenComposeAsync(localVarResponse -> {
            if (localVarResponse.statusCode()/ 100 != 2) {
              return CompletableFuture.failedFuture(getApiException("{{operationId}}", localVarResponse));
            }
            {{#returnType}}
            try {
              String responseBody = localVarResponse.body();
              return CompletableFuture.completedFuture(
                  responseBody == null || responseBody.isBlank() ? null : memberVarObjectMapper.readValue(responseBody, new TypeReference<{{{returnType}}}>() {})
              );
            } catch (IOException e) {
              return CompletableFuture.failedFuture(new ApiException(e));
            }
            {{/returnType}}
            {{^returnType}}
            return CompletableFuture.completedFuture(null);
            {{/returnType}}
      });
    }
    catch (ApiException e) {
      return CompletableFuture.failedFuture(e);
    }
    {{/asyncNative}}
  }

  /**
   * {{summary}}
   * {{notes}}
   {{#allParams}}
   * @param {{paramName}} {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{^isContainer}}{{#defaultValue}}, default to {{.}}{{/defaultValue}}{{/isContainer}}){{/required}}
   {{/allParams}}
   * @return {{#asyncNative}}CompletableFuture&lt;{{/asyncNative}}ApiResponse&lt;{{returnType}}{{^returnType}}Void{{/returnType}}&gt;{{#asyncNative}}&gt;{{/asyncNative}}
   * @throws ApiException if fails to make API call
   {{#isDeprecated}}
   * @deprecated
   {{/isDeprecated}}
   {{#externalDocs}}
   * {{description}}
   * @see <a href="{{url}}">{{summary}} Documentation</a>
   {{/externalDocs}}
   */
  {{#isDeprecated}}
  @Deprecated
  {{/isDeprecated}}
  public {{#asyncNative}}CompletableFuture<{{/asyncNative}}ApiResponse<{{{returnType}}}{{^returnType}}Void{{/returnType}}>{{#asyncNative}}>{{/asyncNative}} {{operationId}}WithHttpInfo({{#allParams}}{{{dataType}}} {{paramName}}{{^-last}}, {{/-last}}{{/allParams}}) throws ApiException {
    {{^asyncNative}}
    HttpRequest.Builder localVarRequestBuilder = {{operationId}}RequestBuilder({{#allParams}}{{paramName}}{{^-last}}, {{/-last}}{{/allParams}});
    try {
      HttpResponse<InputStream> localVarResponse = memberVarHttpClient.send(
          localVarRequestBuilder.build(),
          HttpResponse.BodyHandlers.ofInputStream());
      if (memberVarResponseInterceptor != null) {
        memberVarResponseInterceptor.accept(localVarResponse);
      }
      try {
        if (localVarResponse.statusCode()/ 100 != 2) {
          throw getApiException("{{operationId}}", localVarResponse);
        }
        {{#vendorExtensions.x-java-text-plain-string}}
        // for plain text response
        if (localVarResponse.headers().map().containsKey("Content-Type") &&
                "text/plain".equalsIgnoreCase(localVarResponse.headers().map().get("Content-Type").get(0).split(";")[0].trim())) {
          java.util.Scanner s = new java.util.Scanner(localVarResponse.body()).useDelimiter("\\A");
          String responseBodyText = s.hasNext() ? s.next() : "";
          return new ApiResponse<String>(
                  localVarResponse.statusCode(),
                  localVarResponse.headers().map(),
                  responseBodyText
          );
        } else {
            throw new RuntimeException("Error! The response Content-Type is supposed to be `text/plain` but it's not: " + localVarResponse);
        }
        {{/vendorExtensions.x-java-text-plain-string}}
        {{^vendorExtensions.x-java-text-plain-string}}
        return new ApiResponse<{{{returnType}}}{{^returnType}}Void{{/returnType}}>(
          localVarResponse.statusCode(),
          localVarResponse.headers().map(),
          {{#returnType}}
          localVarResponse.body() == null ? null : memberVarObjectMapper.readValue(localVarResponse.body(), new TypeReference<{{{returnType}}}>() {}) // closes the InputStream
          {{/returnType}}
          {{^returnType}}
          null
          {{/returnType}}
        );
        {{/vendorExtensions.x-java-text-plain-string}}
      } finally {
        {{^returnType}}
        // Drain the InputStream
        while (localVarResponse.body().read() != -1) {
            // Ignore
        }
        localVarResponse.body().close();
        {{/returnType}}
      }
    } catch (IOException e) {
      throw new ApiException(e);
    }
    catch (InterruptedException e) {
      Thread.currentThread().interrupt();
      throw new ApiException(e);
    }
    {{/asyncNative}}
    {{#asyncNative}}
    try {
      HttpRequest.Builder localVarRequestBuilder = {{operationId}}RequestBuilder({{#allParams}}{{paramName}}{{^-last}}, {{/-last}}{{/allParams}});
      return memberVarHttpClient.sendAsync(
          localVarRequestBuilder.build(),
          HttpResponse.BodyHandlers.ofString()).thenComposeAsync(localVarResponse -> {
            if (memberVarAsyncResponseInterceptor != null) {
              memberVarAsyncResponseInterceptor.accept(localVarResponse);
            }
            if (localVarResponse.statusCode()/ 100 != 2) {
              return CompletableFuture.failedFuture(getApiException("{{operationId}}", localVarResponse));
            }
            {{#returnType}}
            try {
              String responseBody = localVarResponse.body();
              return CompletableFuture.completedFuture(
                  new ApiResponse<{{{returnType}}}>(
                      localVarResponse.statusCode(),
                      localVarResponse.headers().map(),
                      responseBody == null || responseBody.isBlank() ? null : memberVarObjectMapper.readValue(responseBody, new TypeReference<{{{returnType}}}>() {}))
              );
            } catch (IOException e) {
              return CompletableFuture.failedFuture(new ApiException(e));
            }
            {{/returnType}}
            {{^returnType}}
            return CompletableFuture.completedFuture(
                new ApiResponse<Void>(localVarResponse.statusCode(), localVarResponse.headers().map(), null)
            );
            {{/returnType}}
        }
      );
    }
    catch (ApiException e) {
      return CompletableFuture.failedFuture(e);
    }
    {{/asyncNative}}
  }

  private HttpRequest.Builder {{operationId}}RequestBuilder({{#allParams}}{{{dataType}}} {{paramName}}{{^-last}}, {{/-last}}{{/allParams}}) throws ApiException {
    {{#allParams}}
    {{#required}}
    // verify the required parameter '{{paramName}}' is set
    if ({{paramName}} == null) {
      throw new ApiException(400, "Missing the required parameter '{{paramName}}' when calling {{operationId}}");
    }
    {{/required}}
    {{/allParams}}

    HttpRequest.Builder localVarRequestBuilder = HttpRequest.newBuilder();

    {{! Switch delimiters for baseName so we can write constants like "{query}" }}
    String localVarPath = "{{{path}}}"{{#pathParams}}
        .replace({{=<% %>=}}"{<%baseName%>}"<%={{ }}=%>, ApiClient.urlEncode({{{paramName}}}.toString())){{/pathParams}};

    {{#hasQueryParams}}
    List<Pair> localVarQueryParams = new ArrayList<>();
    StringJoiner localVarQueryStringJoiner = new StringJoiner("&");
    String localVarQueryParameterBaseName;
    {{#queryParams}}
    localVarQueryParameterBaseName = "{{{baseName}}}";
      {{#collectionFormat}}
    localVarQueryParams.addAll(ApiClient.parameterToPairs("{{{collectionFormat}}}", "{{baseName}}", {{paramName}}));
      {{/collectionFormat}}
      {{^collectionFormat}}
        {{#isDeepObject}}
    if ({{paramName}} != null) {
            {{#isArray}}
      for (int i=0; i < {{paramName}}.size(); i++) {
        localVarQueryStringJoiner.add({{paramName}}.get(i).toUrlQueryString(String.format("{{baseName}}[%d]", i)));
      }
            {{/isArray}}
            {{^isArray}}
      String queryString = {{paramName}}.toUrlQueryString("{{baseName}}");
      if (!queryString.isBlank()) {
        localVarQueryStringJoiner.add(queryString);
      }
            {{/isArray}}
    }
        {{/isDeepObject}}
        {{^isDeepObject}}
            {{#isExplode}}
                {{#hasVars}}
                    {{#vars}}
                        {{#isArray}}
    localVarQueryParams.addAll(ApiClient.parameterToPairs("multi", "{{baseName}}", {{paramName}}.{{getter}}()));
                        {{/isArray}}
                        {{^isArray}}
    localVarQueryParams.addAll(ApiClient.parameterToPairs("{{baseName}}", {{paramName}}.{{getter}}()));
                        {{/isArray}}
                    {{/vars}}
                {{/hasVars}}
                {{^hasVars}}
                {{#isModel}}
    localVarQueryStringJoiner.add({{paramName}}.toUrlQueryString());
                {{/isModel}}
                {{^isModel}}
    localVarQueryParams.addAll(ApiClient.parameterToPairs("{{baseName}}", {{paramName}}));
                {{/isModel}}
                {{/hasVars}}
            {{/isExplode}}
            {{^isExplode}}
    localVarQueryParams.addAll(ApiClient.parameterToPairs("{{baseName}}", {{paramName}}));
            {{/isExplode}}
        {{/isDeepObject}}
      {{/collectionFormat}}
    {{/queryParams}}

    if (!localVarQueryParams.isEmpty() || localVarQueryStringJoiner.length() != 0) {
      StringJoiner queryJoiner = new StringJoiner("&");
      localVarQueryParams.forEach(p -> queryJoiner.add(p.getName() + '=' + p.getValue()));
      if (localVarQueryStringJoiner.length() != 0) {
        queryJoiner.add(localVarQueryStringJoiner.toString());
      }
      localVarRequestBuilder.uri(URI.create(memberVarBaseUri + localVarPath + '?' + queryJoiner.toString()));
    } else {
      localVarRequestBuilder.uri(URI.create(memberVarBaseUri + localVarPath));
    }
    {{/hasQueryParams}}
    {{^hasQueryParams}}
    localVarRequestBuilder.uri(URI.create(memberVarBaseUri + localVarPath));
    {{/hasQueryParams}}

    {{#headerParams}}
    if ({{paramName}} != null) {
      localVarRequestBuilder.header("{{baseName}}", {{paramName}}.toString());
    }
    {{/headerParams}}
    {{#bodyParam}}
    localVarRequestBuilder.header("Content-Type", "{{#hasConsumes}}{{#consumes}}{{#-first}}{{{mediaType}}}{{/-first}}{{/consumes}}{{/hasConsumes}}{{#hasConsumes}}{{^consumes}}application/json{{/consumes}}{{/hasConsumes}}{{^hasConsumes}}application/json{{/hasConsumes}}");
    {{/bodyParam}}
    localVarRequestBuilder.header("Accept", "{{#hasProduces}}{{#produces}}{{{mediaType}}}{{^-last}}, {{/-last}}{{/produces}}{{/hasProduces}}{{#hasProduces}}{{^produces}}application/json{{/produces}}{{/hasProduces}}{{^hasProduces}}application/json{{/hasProduces}}");

    {{#bodyParam}}
    {{#isString}}
    localVarRequestBuilder.method("{{httpMethod}}", HttpRequest.BodyPublishers.ofString({{paramName}}));
    {{/isString}}
    {{^isString}}
    try {
      byte[] localVarPostBody = memberVarObjectMapper.writeValueAsBytes({{paramName}});
      localVarRequestBuilder.method("{{httpMethod}}", HttpRequest.BodyPublishers.ofByteArray(localVarPostBody));
    } catch (IOException e) {
      throw new ApiException(e);
    }
    {{/isString}}
    {{/bodyParam}}
    {{^bodyParam}}
    {{#hasFormParams}}
    {{#isMultipart}}
    MultipartEntityBuilder multiPartBuilder = MultipartEntityBuilder.create();
    boolean hasFiles = false;
    {{#formParams}}
    {{#isArray}}
    for (int i=0; i < {{paramName}}.size(); i++) {
        {{#isFile}}
        multiPartBuilder.addBinaryBody("{{{baseName}}}", {{paramName}}.get(i));
        hasFiles = true;
        {{/isFile}}
        {{^isFile}}
        multiPartBuilder.addTextBody("{{{baseName}}}", {{paramName}}.get(i).toString());
        {{/isFile}}
    }
    {{/isArray}}
    {{^isArray}}
    {{#isFile}}
    multiPartBuilder.addBinaryBody("{{{baseName}}}", {{paramName}});
    hasFiles = true;
    {{/isFile}}
    {{^isFile}}
    multiPartBuilder.addTextBody("{{{baseName}}}", {{paramName}}.toString());
    {{/isFile}}
    {{/isArray}}
    {{/formParams}}
    HttpEntity entity = multiPartBuilder.build();
    HttpRequest.BodyPublisher formDataPublisher;
    if (hasFiles) {
        Pipe pipe;
        try {
            pipe = Pipe.open();
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        new Thread(() -> {
            try (OutputStream outputStream = Channels.newOutputStream(pipe.sink())) {
                entity.writeTo(outputStream);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }).start();
        formDataPublisher = HttpRequest.BodyPublishers.ofInputStream(() -> Channels.newInputStream(pipe.source()));
    } else {
        ByteArrayOutputStream formOutputStream = new ByteArrayOutputStream();
        try {
            entity.writeTo(formOutputStream);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        formDataPublisher = HttpRequest.BodyPublishers
            .ofInputStream(() -> new ByteArrayInputStream(formOutputStream.toByteArray()));
    }
    localVarRequestBuilder
        .header("Content-Type", entity.getContentType().getValue())
        .method("{{httpMethod}}", formDataPublisher);
    {{/isMultipart}}
    {{^isMultipart}}
    List<NameValuePair> formValues = new ArrayList<>();
    {{#formParams}}
    {{#isArray}}
    for (int i=0; i < {{paramName}}.size(); i++) {
        if ({{paramName}}.get(i) != null) {
            formValues.add(new BasicNameValuePair("{{{baseName}}}", {{paramName}}.get(i).toString()));
        }
    }
    {{/isArray}}
    {{^isArray}}
    if ({{paramName}} != null) {
        formValues.add(new BasicNameValuePair("{{{baseName}}}", {{paramName}}.toString()));
    }
    {{/isArray}}
    {{/formParams}}
    HttpEntity entity = new UrlEncodedFormEntity(formValues, java.nio.charset.StandardCharsets.UTF_8);
    ByteArrayOutputStream formOutputStream = new ByteArrayOutputStream();
    try {
        entity.writeTo(formOutputStream);
    } catch (IOException e) {
        throw new RuntimeException(e);
    }
    localVarRequestBuilder
        .header("Content-Type", entity.getContentType().getValue())
        .method("{{httpMethod}}", HttpRequest.BodyPublishers
            .ofInputStream(() -> new ByteArrayInputStream(formOutputStream.toByteArray())));
    {{/isMultipart}}
    {{/hasFormParams}}
    {{^hasFormParams}}
    localVarRequestBuilder.method("{{httpMethod}}", HttpRequest.BodyPublishers.noBody());
    {{/hasFormParams}}
    {{/bodyParam}}
    if (memberVarReadTimeout != null) {
      localVarRequestBuilder.timeout(memberVarReadTimeout);
    }
    if (memberVarInterceptor != null) {
      memberVarInterceptor.accept(localVarRequestBuilder);
    }
    return localVarRequestBuilder;
  }

  {{#vendorExtensions.x-group-parameters}}
  {{#hasParams}}

  public static final class API{{operationId}}Request {
    {{#requiredParams}}
    private {{{dataType}}} {{paramName}}; // {{description}} (required)
    {{/requiredParams}}
    {{#optionalParams}}
    private {{{dataType}}} {{paramName}}; // {{description}} (optional{{^isContainer}}{{#defaultValue}}, default to {{.}}{{/defaultValue}}{{/isContainer}})
    {{/optionalParams}}

    private API{{operationId}}Request(Builder builder) {
      {{#requiredParams}}
      this.{{paramName}} = builder.{{paramName}};
      {{/requiredParams}}
      {{#optionalParams}}
      this.{{paramName}} = builder.{{paramName}};
      {{/optionalParams}}
    }
    {{#allParams}}
    public {{{dataType}}} {{paramName}}() {
      return {{paramName}};
    }
    {{/allParams}}
    public static Builder newBuilder() {
      return new Builder();
    }

    public static class Builder {
      {{#requiredParams}}
      private {{{dataType}}} {{paramName}};
      {{/requiredParams}}
      {{#optionalParams}}
      private {{{dataType}}} {{paramName}};
      {{/optionalParams}}

      {{#allParams}}
      public Builder {{paramName}}({{{dataType}}} {{paramName}}) {
        this.{{paramName}} = {{paramName}};
        return this;
      }
      {{/allParams}}
      public API{{operationId}}Request build() {
        return new API{{operationId}}Request(this);
      }
    }
  }

  {{/hasParams}}
  {{/vendorExtensions.x-group-parameters}}
  {{/operation}}
}
{{/operations}}
